'use strict';
var vk; // 全局vk实例
// 涉及的表名
const dbName = require("../../../dao/config.js");

var db = uniCloud.database(); // 全局数据库引用
var _ = db.command; // 数据库操作符
var $ = _.aggregate; // 聚合查询操作符
/**
 * 权限注意：访问以下链接查看
 * 文档地址：https://vkdoc.fsq.pub/client/uniCloud/cloudfunctions/cloudObject.html#内置权限
 */
var cloudObject = {
	isCloudObject: true, // 标记为云对象模式
	/**
	 * 请求前处理，主要用于调用方法之前进行预处理，一般用于拦截器、统一的身份验证、参数校验、定义全局对象等。
	 * 文档地址：https://vkdoc.fsq.pub/client/uniCloud/cloudfunctions/cloudObject.html#before-预处理
	 */
	_before: async function() {
		vk = this.vk; // 将vk定义为全局对象
		// let { customUtil, uniID, config, pubFun } = this.getUtil(); // 获取工具包
	},
	/**
	 * 请求后处理，主要用于处理本次调用方法的返回结果或者抛出的错误
	 * 文档地址：https://vkdoc.fsq.pub/client/uniCloud/cloudfunctions/cloudObject.html#after-后处理
	 */
	_after: async function(options) {
		let { err, res } = options;
		if (err) {
			return; // 如果方法抛出错误，直接return;不处理
		}
		return res;
	},
	/**
	 * 用户统计人数
	 * @url admin/business/kh.stats.getUserCount 前端调用的url参数地址
	 */
	getUserCount: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let { todayStart, todayEnd, yesterdayStart, yesterdayEnd } = vk.pubfn.getCommonTime();
		let day7Start = vk.pubfn.getOffsetTime(todayStart, {
			day: 7,
			mode: "before", // after 之后 before 之前
		});
		// 并发
		let batchRunRes = await vk.pubfn.batchRun({
			// 主执行函数
			main: [
				// 总用户数量
				async () => {
						return await vk.daoCenter.userDao.count();
					},
					// 今日新增用户数量
					async () => {
							return await vk.daoCenter.userDao.count({
								register_date: _.gte(todayStart).lte(todayEnd)
							});
						},
						// 昨日新增用户数量
						async () => {
								return await vk.daoCenter.userDao.count({
									register_date: _.gte(yesterdayStart).lte(yesterdayEnd)
								});
							},
							// 近7天新增用户数量
							async () => {
								return await vk.daoCenter.userDao.count({
									register_date: _.gte(day7Start).lte(todayEnd)
								});
							}
			],
			// 最大并发量，如果设置为1，则会按顺序执行
			concurrency: 10
		});
		res.list = batchRunRes.stack;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 用户新增统计,按日或月
	 * @url admin/business/kh.stats.getNewUserCountGroup 前端调用的url参数地址
	 */
	getNewUserCountGroup: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			mode = "日"
		} = data;
		let group = "新增数";
		let timeFormat;
		let boundaries = [];
		if (mode === "时") {
			// 小时
			let { hourStart } = vk.pubfn.getCommonTime(new Date());
			// 在今日的时间上往前推24小时
			for (let i = -1; i < 24; i++) {
				let timeCalc = vk.pubfn.getOffsetTime(hourStart, {
					hours: i,
					mode: "before", // after 之后 before 之前
				});
				boundaries.push(timeCalc);
			}
			timeFormat = "h时";
		} else if (mode === "日") {
			// 日
			let { todayStart } = vk.pubfn.getCommonTime();
			// 在今日的时间上往前推
			for (let i = -1; i < 28; i++) {
				let timeCalc = vk.pubfn.getOffsetTime(todayStart, {
					day: i,
					mode: "before", // after 之后 before 之前
				});
				boundaries.push(timeCalc);
			}
			timeFormat = "MM-dd";
		} else {
			// 月
			let { monthStart } = vk.pubfn.getCommonTime();
			// 在今日的时间上往前推12个月
			for (let i = -1; i < 12; i++) {
				let timeCalc = vk.pubfn.getOffsetTime(monthStart, {
					month: i,
					mode: "before", // after 之后 before 之前
				});
				boundaries.push(timeCalc);
			}
			timeFormat = "M月";
		}

		// 数组顺序反转（必须从小到大排序）
		boundaries.reverse();
		// 数据库查询
		let dbRes = await db.collection(dbName.user).aggregate()
			.match({
				register_date: _.gte(boundaries[0]).lte(boundaries[boundaries.length - 1]),
			})
			.bucket({
				groupBy: '$register_date',
				boundaries,
				default: 'other',
				output: {
					count: $.sum(1)
				}
			})
			.end()

		// 组装数据返回
		res.list = boundaries.map((groupItem) => {
			let findItem = dbRes.data.find((item) => {
				return item._id === groupItem;
			});
			let text = vk.pubfn.timeFormat(groupItem, timeFormat);
			let value = findItem && findItem.count ? findItem.count : 0;
			return { value, text, group };
		});
		// 删除最后一个数据
		res.list.pop();

		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 用户登录统计,按日或月
	 * @url admin/business/kh.stats.getUserLoginCountGroup 前端调用的url参数地址
	 */
	getUserLoginCountGroup: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			mode = "日"
		} = data;
		let group = "登录用户数量";
		let timeFormat;
		let boundaries = [];
		if (mode === "时") {
			// 小时
			let { hourStart } = vk.pubfn.getCommonTime(new Date());
			// 在今日的时间上往前推24小时
			for (let i = -1; i < 24; i++) {
				let timeCalc = vk.pubfn.getOffsetTime(hourStart, {
					hours: i,
					mode: "before", // after 之后 before 之前
				});
				boundaries.push(timeCalc);
			}
			timeFormat = "h时";
		} else if (mode === "日") {
			// 日
			let { todayStart } = vk.pubfn.getCommonTime();
			// 在今日的时间上往前推
			for (let i = -1; i < 28; i++) {
				let timeCalc = vk.pubfn.getOffsetTime(todayStart, {
					day: i,
					mode: "before", // after 之后 before 之前
				});
				boundaries.push(timeCalc);
			}
			timeFormat = "MM-dd";
		} else {
			// 月
			let { monthStart } = vk.pubfn.getCommonTime();
			// 在今日的时间上往前推12个月
			for (let i = -1; i < 12; i++) {
				let timeCalc = vk.pubfn.getOffsetTime(monthStart, {
					month: i,
					mode: "before", // after 之后 before 之前
				});
				boundaries.push(timeCalc);
			}
			timeFormat = "M月";
		}

		// 数组顺序反转（必须从小到大排序）
		boundaries.reverse();
		// 数据库查询
		let dbRes = await db.collection(dbName.loginLog).aggregate()
			.match({
				_add_time: _.gte(boundaries[0]).lte(boundaries[boundaries.length - 1]),
			})
			.bucket({
				groupBy: '$_add_time',
				boundaries,
				default: 'other',
				output: {
					count: $.addToSet('$user_id')
				}
			})
			.addFields({
				count: $.size('$count')
			})
			.end()

		// 组装数据返回
		res.list = boundaries.map((groupItem) => {
			let findItem = dbRes.data.find((item) => {
				return item._id === groupItem;
			});
			let text = vk.pubfn.timeFormat(groupItem, timeFormat);
			let value = findItem && findItem.count ? findItem.count : 0;
			return { value, text, group };
		});
		// 删除最后一个数据
		res.list.pop();


		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 性别比例
	 * @url admin/business/kh.stats.getUserGenderCountGroup 前端调用的url参数地址
	 */
	getUserGenderCountGroup: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let list = await vk.baseDao.selects({
			dbName: dbName.user,
			pageIndex: 1,
			pageSize: 10,
			getMain: true,
			// 主表where条件
			whereJson: {

			},
			groupJson: {
				_id: "$gender", // _id是分组id， $ 后面接字段名，如user_id字段进行分组
				count: _.$.sum(1), // $ 后面接字段名，sum(1)代表求记录数量
			}
		});
		let boundaries = ["未知", "男", "女"];
		// 组装数据返回
		res.list = boundaries.map((groupItem, groupIndex) => {
			let findItem = list.find((item) => {
				if (!groupIndex && !item._id) {
					return true;
				}
				return item._id === groupIndex;
			});
			let text = groupItem;
			let value = findItem && findItem.count ? findItem.count : 0;
			return { value, text };
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 会员等级人数统计
	 * @url admin/business/kh.stats.getVipLvCountGroup 前端调用的url参数地址
	 */
	getVipLvCountGroup: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let list = await vk.baseDao.selects({
			dbName: dbName.user,
			pageIndex: 1,
			pageSize: 100,
			getMain: true,
			// 主表where条件
			whereJson: {

			},
			groupJson: {
				_id: "$vip_lv", // _id是分组id， $ 后面接字段名，如user_id字段进行分组
				count: _.$.sum(1), // $ 后面接字段名，sum(1)代表求记录数量
			}
		});
		let mchInfo = await vk.daoCenter.mchDao.find();
		let { vip_level_rule } = mchInfo;

		// 组装数据返回
		res.list = vip_level_rule.map((groupItem, groupIndex) => {
			let findItem = list.find((item) => {
				return item._id === groupItem.lv;
			});
			let text = groupItem.name;
			let value = findItem && findItem.count ? findItem.count : 0;
			return { value, text };
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 分销等级人数统计
	 * @url admin/business/kh.stats.getFxLvCountGroup 前端调用的url参数地址
	 */
	getFxLvCountGroup: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let list = await vk.baseDao.selects({
			dbName: dbName.user,
			pageIndex: 1,
			pageSize: 100,
			getMain: true,
			// 主表where条件
			whereJson: {

			},
			groupJson: {
				_id: "$fx.lv", // _id是分组id， $ 后面接字段名，如user_id字段进行分组
				count: _.$.sum(1), // $ 后面接字段名，sum(1)代表求记录数量
			}
		});
		let mchInfo = await vk.daoCenter.mchDao.find();
		let { level_rule } = mchInfo.fx;

		// 组装数据返回
		res.list = level_rule.map((groupItem, groupIndex) => {
			let findItem = list.find((item) => {
				return item._id === groupItem.lv;
			});
			let text = groupItem.name;
			let value = findItem && findItem.count ? findItem.count : 0;
			return { value, text };
		});

		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 订单统计,按日或月
	 * @url admin/business/kh.stats.getOrderCountGroup 前端调用的url参数地址
	 */
	getOrderCountGroup: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			mode = "日"
		} = data;
		let group = "支付订单数量";
		let timeFormat;
		let boundaries = [];
		if (mode === "时") {
			// 小时
			let { hourStart } = vk.pubfn.getCommonTime(new Date());
			// 在今日的时间上往前推24小时
			for (let i = -1; i < 24; i++) {
				let timeCalc = vk.pubfn.getOffsetTime(hourStart, {
					hours: i,
					mode: "before", // after 之后 before 之前
				});
				boundaries.push(timeCalc);
			}
			timeFormat = "h时";
		} else if (mode === "日") {
			// 日
			let { todayStart } = vk.pubfn.getCommonTime();
			// 在今日的时间上往前推
			for (let i = -1; i < 28; i++) {
				let timeCalc = vk.pubfn.getOffsetTime(todayStart, {
					day: i,
					mode: "before", // after 之后 before 之前
				});
				boundaries.push(timeCalc);
			}
			timeFormat = "MM-dd";
		} else {
			// 月
			let { monthStart } = vk.pubfn.getCommonTime();
			// 在今日的时间上往前推12个月
			for (let i = -1; i < 12; i++) {
				let timeCalc = vk.pubfn.getOffsetTime(monthStart, {
					month: i,
					mode: "before", // after 之后 before 之前
				});
				boundaries.push(timeCalc);
			}
			timeFormat = "M月";
		}

		// 数组顺序反转（必须从小到大排序）
		boundaries.reverse();
		// 数据库查询
		let dbRes = await db.collection(dbName.order).aggregate()
			.match({
				status: _.gt(0),
				pay_time: _.gte(boundaries[0]).lte(boundaries[boundaries.length - 1]),
			})
			.bucket({
				groupBy: '$pay_time',
				boundaries,
				default: 'other',
				output: {
					count: $.sum(1)
				}
			})
			.end()

		// 组装数据返回
		res.list = boundaries.map((groupItem) => {
			let findItem = dbRes.data.find((item) => {
				return item._id === groupItem;
			});
			let text = vk.pubfn.timeFormat(groupItem, timeFormat);
			let value = findItem && findItem.count ? findItem.count : 0;
			return { value, text, group };
		});
		// 删除最后一个数据
		res.list.pop();

		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 订单统计,按日或月(退款)
	 * @url admin/business/kh.stats.getRefundOrderCountGroup 前端调用的url参数地址
	 */
	getRefundOrderCountGroup: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			mode = "日"
		} = data;
		let group = "退款订单数量";
		let timeFormat;
		let boundaries = [];
		if (mode === "时") {
			// 小时
			let { hourStart } = vk.pubfn.getCommonTime(new Date());
			// 在今日的时间上往前推24小时
			for (let i = -1; i < 24; i++) {
				let timeCalc = vk.pubfn.getOffsetTime(hourStart, {
					hours: i,
					mode: "before", // after 之后 before 之前
				});
				boundaries.push(timeCalc);
			}
			timeFormat = "h时";
		} else if (mode === "日") {
			// 日
			let { todayStart } = vk.pubfn.getCommonTime();
			// 在今日的时间上往前推
			for (let i = -1; i < 28; i++) {
				let timeCalc = vk.pubfn.getOffsetTime(todayStart, {
					day: i,
					mode: "before", // after 之后 before 之前
				});
				boundaries.push(timeCalc);
			}
			timeFormat = "MM-dd";
		} else {
			// 月
			let { monthStart } = vk.pubfn.getCommonTime();
			// 在今日的时间上往前推12个月
			for (let i = -1; i < 12; i++) {
				let timeCalc = vk.pubfn.getOffsetTime(monthStart, {
					month: i,
					mode: "before", // after 之后 before 之前
				});
				boundaries.push(timeCalc);
			}
			timeFormat = "M月";
		}

		// 数组顺序反转（必须从小到大排序）
		boundaries.reverse();
		// 数据库查询
		let dbRes = await db.collection(dbName.order).aggregate()
			.match({
				status: _.in([-3, -4]),
				refund_time: _.gte(boundaries[0]).lte(boundaries[boundaries.length - 1]),
			})
			.bucket({
				groupBy: '$refund_time',
				boundaries,
				default: 'other',
				output: {
					count: $.sum(1)
				}
			})
			.end()

		// 组装数据返回
		res.list = boundaries.map((groupItem) => {
			let findItem = dbRes.data.find((item) => {
				return item._id === groupItem;
			});
			let text = vk.pubfn.timeFormat(groupItem, timeFormat);
			let value = findItem && findItem.count ? findItem.count : 0;
			return { value, text, group };
		});
		// 删除最后一个数据
		res.list.pop();

		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 订单数量统计
	 * @url admin/business/kh.stats.getOrderCount 前端调用的url参数地址
	 */
	getOrderCount: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let { todayStart, todayEnd, yesterdayStart, yesterdayEnd } = vk.pubfn.getCommonTime();
		let day7Start = vk.pubfn.getOffsetTime(todayStart, {
			day: 7,
			mode: "before", // after 之后 before 之前
		});
		// 并发
		let batchRunRes = await vk.pubfn.batchRun({
			// 主执行函数
			main: [
				// 总数量
				async () => {
						return await vk.daoCenter.orderDao.count();
					},
					// 今日数量
					async () => {
							return await vk.daoCenter.orderDao.count({
								pay_time: _.gte(todayStart).lte(todayEnd)
							});
						},
						// 昨日数量
						async () => {
								return await vk.daoCenter.orderDao.count({
									pay_time: _.gte(yesterdayStart).lte(yesterdayEnd)
								});
							},
							// 近7天数量
							async () => {
								return await vk.daoCenter.orderDao.count({
									pay_time: _.gte(day7Start).lte(todayEnd)
								});
							}
			],
			// 最大并发量，如果设置为1，则会按顺序执行
			concurrency: 10
		});
		res.list = batchRunRes.stack;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 订单状态分组
	 * @url admin/business/kh.stats.getOrderStatusGroup 前端调用的url参数地址
	 */
	getOrderStatusGroup: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let status = [0, 1, 2, 3, -2];
		let list = await vk.baseDao.selects({
			dbName: dbName.order,
			pageIndex: 1,
			pageSize: 10,
			getMain: true,
			// 主表where条件
			whereJson: {
				status: _.in(status)
			},
			groupJson: {
				_id: "$status", // _id是分组id， $ 后面接字段名，如user_id字段进行分组
				count: _.$.sum(1), // $ 后面接字段名，sum(1)代表求记录数量
			}
		});
		// 组装数据返回
		res.list = status.map((groupItem) => {
			let findItem = list.find((item) => {
				return item._id === groupItem;
			});
			let text = groupItem;
			let value = findItem && findItem.count ? findItem.count : 0;
			return value;
		});

		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 商品数量统计
	 * @url admin/business/kh.stats.getGoodsCount 前端调用的url参数地址
	 */
	getGoodsCount: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		// 并发
		let batchRunRes = await vk.pubfn.batchRun({
			// 主执行函数
			main: [
				// 总数量
				async () => {
						return await vk.daoCenter.goodsDao.count({
							status: _.in([1, 2])
						});
					},
					// 销售中
					async () => {
							return await vk.daoCenter.goodsDao.count({
								status: 1,
								is_on_sale: true
							});
						},
						// 已缺货
						async () => {
								return await vk.daoCenter.goodsDao.count({
									status: 1,
									is_on_sale: true,
									stock: 0
								});
							},
							// 回收站
							async () => {
								return await vk.daoCenter.goodsDao.count({
									status: 3
								});
							}
			],
			// 最大并发量，如果设置为1，则会按顺序执行
			concurrency: 10
		});
		res.list = batchRunRes.stack;
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 商品销量排行榜
	 * @url admin/business/kh.stats.getGoodsSellRank 前端调用的url参数地址
	 */
	getGoodsSellRank: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let {
			mode = "count"
		} = data;
		let groupJson = {
			_id: "$goods_id",
		};
		let sortArr = [];
		let group = "";
		if (mode === "count") {
			groupJson["total"] = _.$.sum("$buy_num");
			group = "商品销量";
		} else {
			groupJson["total"] = _.$.sum("$amount.goods_payment_amount");
			group = "商品销售额";
		}
		let list = await vk.baseDao.selects({
			dbName: dbName.userGoodsPer,
			pageIndex: 1,
			pageSize: 10,
			getMain: true,
			// 主表where条件
			whereJson: {

			},
			groupJson,
			sortArr: [{ name: "total", type: "desc" }],
			// 副表列表
			foreignDB: [{
				dbName: dbName.goods,
				localKey: "_id",
				foreignKey: "_id",
				as: "goodsInfo",
				limit: 1,
				fieldJson: { name: 1, goods_thumb: 1 },
			}]
		});
		// 组装数据返回
		res.list = list.map((groupItem) => {
			let text = groupItem.goodsInfo.name;
			let value = groupItem.total;
			if (mode === "amount") {
				value = vk.pubfn.toDecimal(value / 100, 2);
			}
			return { value, text, group };
		});
		if (vk.pubfn.isNull(res.list)){
			res.list = [
				{ value:0, text:"暂无数据", group }
			];
		};
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 商品浏览量排行
	 * @url admin/business/kh.stats.getGoodsViewCount 前端调用的url参数地址
	 */
	getGoodsViewCount: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------
		let list = await vk.baseDao.select({
			dbName: dbName.goods,
			getCount: false,
			pageIndex: 1,
			pageSize: 20,
			getMain: true,
			whereJson: {
				status: 1
			},
			sortArr: [{ name: "view_count", type: "desc" }],
		});
		// 组装数据返回
		res.list = list.map((groupItem) => {
			let text = groupItem.name;
			let value = groupItem.view_count;
			let group = "商品浏览量";
			return { value, text, group };
		});
		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
	/**
	 * 模板函数
	 * @url admin/business/kh.stats.test 前端调用的url参数地址
	 */
	test: async function(data) {
		let res = { code: 0, msg: '' };
		// 业务逻辑开始-----------------------------------------------------------


		// 业务逻辑结束-----------------------------------------------------------
		return res;
	},
};

module.exports = cloudObject;
